home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1995, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * UNPUBLISHED -- Rights reserved under the copyright laws of the United
- * States. Use of a copyright notice is precautionary only and does not
- * imply publication or disclosure.
- *
- * THIS SOFTWARE CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION OF
- * SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, DISTRIBUTION, OR
- * DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN
- * PERMISSION OF SILICON GRAPHICS, INC.
- *
- * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the
- * Rights in Technical Data and Computer Software clause at DFARS 252.227-7013
- * and/or in similar or successor clauses in the FAR, or the DOD or NASA FAR
- * Supplement. Unpublished-- rights reserved under the copyright laws of the
- * United States. Contractor/manufacturer is Silicon Graphics, Inc.,
- * 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <GL/gl.h>
- #include <GL/glc.h>
- #include <GL/glu.h>
- #include <Xm/Xm.h>
- #include <Xm/Form.h>
- #include <Xm/Frame.h>
- #include <Xm/RowColumn.h>
- #include <Xm/ToggleBG.h>
- #include <Xm/CascadeBG.h>
- #include <X11/keysym.h>
- #include <GL/GLwMDrawA.h>
- #include <alloca.h>
-
-
- int attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1,
- GLX_GREEN_SIZE, 1, None};
-
- String fallbackResources[] = {
- "*sgiMode: True",
- "*useSchemes: all",
- "*canvas.width: 300", "*canvas.height: 300",
- "*frame.shadowType: SHADOW_IN",
- NULL};
-
- GLuint contextID;
- GLfloat rotX, rotY, rotZ, scale;
- GLfloat transX, transY, transZ;
- GLfloat origX, origY;
- GLfloat zsize;
- GLfloat bounds[8];
- int glx_width, glx_height;
-
- GLint fontID, *fontIDs, fontCount;
- char **fontNames;
-
- char *default_str = "hello, world!";
- char *render_str;
-
- int drawStyle;
- int use_ortho;
-
- enum {
- XX_BITMAP,
- XX_TRIANGLE,
- XX_LINE,
- XX_RESETVIEW,
- XX_RESETMODE,
- XX_ORTHO,
- XX_QUIT,
- NULL_COMMAND
- };
-
- GLXContext glxctx;
- Widget canvas;
- Widget *menu_buttons;
- int fontBase;
-
- /* menus */
- typedef struct {
- char *label;
- int cmd;
- } MenuItem;
-
- typedef struct {
- char *label;
- int icount;
- MenuItem *items;
- } MenuPane;
-
- MenuItem view_items[] = {
- { "Reset View", XX_RESETVIEW },
- { "Reset Modes", XX_RESETMODE },
- { "Ortho Projection", XX_ORTHO },
- { "Quit", XX_QUIT },
- };
-
- MenuItem style_items[] = {
- { "GLC_BITMAP", XX_BITMAP },
- { "GLC_TRIANGLE", XX_TRIANGLE },
- { "GLC_LINE", XX_LINE },
- };
-
- MenuPane view_menu = { "View", XtNumber(view_items), view_items };
- MenuPane style_menu = { "Render Style", XtNumber(style_items), style_items };
-
- void InitFonts(void)
- {
- int ii;
- char *ptr;
-
- if ((contextID = glcGenContext()) == 0) {
- printf("Died at glcGenContext\n");
- exit(1);
- }
-
- glcContext(contextID);
- if (glcGetError() != GL_NO_ERROR) {
- printf("Died at glcContext\n");
- exit(1);
- }
-
- fontCount = glcGeti(GLC_MASTER_COUNT);
- if (glcGetError() != GL_NO_ERROR) {
- printf("Died at glcGeti\n");
- exit(1);
- }
-
- if (fontCount <= 0) {
- fprintf(stderr, "No available fonts\n");
- exit(1);
- }
-
- fontIDs = (GLint *) malloc ( fontCount * sizeof(GLint) );
- bzero(fontIDs, fontCount * sizeof(GLint));
- fontNames = (char **) malloc ( fontCount * sizeof(char *) );
-
- for (ii = 0; ii < fontCount; ii++) {
- fontNames[ii] = strdup((char *)glcGetMasterc(ii, GLC_FAMILY));
- #if 0
- /* We *could* load all the fonts now, but it slows initialization.
- * Instead we'll lazy-load them.
- */
- fontIDs[ii] = glcGenFontID();
- if (glcNewFontFromMaster(fontIDs[ii], ii) != fontIDs[ii]) {
- printf("Died at glcNewFontFromMaster\n");
- exit(1);
- }
- #endif
- }
-
- fontID = -1;
- }
-
- void set_toggle(int button, int set)
- {
- XmToggleButtonGadgetSetState(menu_buttons[button], set, False);
- }
-
- void set_font(int id)
- {
- if (fontID >= 0)
- set_toggle(fontID + fontBase, False);
-
- fontID = id;
- set_toggle(fontID + fontBase, True);
-
- if (!fontIDs[id]) {
- fontIDs[id] = glcGenFontID();
- if (glcNewFontFromMaster(fontIDs[id], id) != fontIDs[id]) {
- printf("Died at glcNewFontFromMaster\n");
- exit(1);
- }
- }
-
- glcFont(fontIDs[fontID]);
- }
-
- void set_draw_style(int style)
- {
- int ii;
- for (ii = XX_BITMAP; ii <= XX_LINE; ii++)
- set_toggle(ii, style == ii);
-
- switch (style) {
- case XX_BITMAP:
- drawStyle = GLC_BITMAP;
- break;
- case XX_LINE:
- drawStyle = GLC_LINE;
- break;
- case XX_TRIANGLE:
- default:
- drawStyle = GLC_TRIANGLE;
- break;
- }
- glcRenderStyle(drawStyle);
- }
-
- void reset_bounds()
- {
- GLfloat width = 0.0, height = 0.0;
-
- if (drawStyle == GLC_BITMAP)
- glcLoadIdentity();
- if (glcMeasureString(GL_TRUE, render_str) != 0) {
- glcGetStringMetric(GLC_BOUNDS, bounds);
- width = bounds[2] - bounds[0];
- height = bounds[5] - bounds[3];
- }
- origX = - width / 2.0;
- origY = - height / 2.0;
- }
-
- void reset_view()
- {
- set_toggle(XX_RESETVIEW, False);
-
- rotX = rotY = rotZ = 0.0;
- scale = 55.0;
- transX = 0.0;
- transY = 0.0;
- transZ = 0.0;
- zsize = 10.0;
- reset_bounds();
- }
-
- void reset_modes()
- {
- set_toggle(XX_RESETMODE, False);
- set_draw_style(XX_LINE);
- use_ortho = False;
- if (render_str && render_str != default_str)
- free(render_str);
- render_str = default_str;
- }
-
- void redraw(void)
- {
- glClear(GL_COLOR_BUFFER_BIT);
-
- glPushMatrix();
- glTranslatef(transX, transY, transZ);
- glScalef(scale, scale, 1.0);
- glRotatef(rotX, 1.0, 0.0, 0.0);
- glRotatef(rotY, 0.0, 1.0, 0.0);
- glRotatef(rotZ, 0.0, 0.0, 1.0);
- glTranslatef(origX, origY, 0.0);
-
- /* Draw the bounding box */
- glColor3f(1.0, 1.0, 1.0);
- glBegin(GL_LINE_LOOP);
- glVertex3f(bounds[0], bounds[1], 0.0);
- glVertex3f(bounds[2], bounds[3], 0.0);
- glVertex3f(bounds[4], bounds[5], 0.0);
- glVertex3f(bounds[6], bounds[7], 0.0);
- glEnd();
-
-
- if (drawStyle != GLC_BITMAP) {
- glColor3f(0.0, 1.0, 0.0);
- glcRenderString(render_str);
- glPopMatrix();
- } else {
- #if 1
- /* This section is a hack to ensure that the raster position is
- * valid and the string is not clipped, even if the origin is
- * outside the viewport. First we calculate the transformed
- * origin...
- */
- GLdouble mvmat[16], prjmat[16], x, y, z;
- GLint vp[4];
- glGetDoublev(GL_MODELVIEW_MATRIX, mvmat);
- glGetDoublev(GL_PROJECTION_MATRIX, prjmat);
- glGetIntegerv(GL_VIEWPORT, vp);
- gluProject(0, 0, 0, mvmat, prjmat, vp, &x, &y, &z);
-
- /* Now pop the transformation since we no longer need it */
- glPopMatrix();
-
- /* Map window coordinates to world coordinates */
- x -= vp[2] >> 1;
- y -= vp[3] >> 1;
-
- /* Set the raster position to something valid (0,0) and translate
- * it to the transformed origin. This keeps it valid, even though
- * it may be outside of the viewport!
- */
- glColor3f(1.0, 0.0, 0.0);
- glRasterPos3f(0, 0, z);
- glBitmap(0, 0, 0, 0, x, y, NULL);
- glcLoadIdentity();
- glcScale(scale, scale);
- glcRotate(-rotZ);
- glcRenderString(render_str);
- #else
- /* If we don't care about the string being clipped, we could always
- * specify the raster position directly. Here, (0,0) is transformed
- * to the desired raster position. Note that moving the origin
- * outside of the viewport clips the entire string.
- */
- glColor3f(1.0, 0.0, 0.0);
- glRasterPos3f(0, 0, 0);
- glcLoadIdentity();
- glcScale(scale, scale);
- glcRotate(-rotZ);
- glcRenderString(render_str);
- glPopMatrix();
- #endif
- }
-
-
- if (glcGetError() != GL_NO_ERROR) {
- printf("Got a GLC error\n");
- exit(1);
- }
-
- glXSwapBuffers(XtDisplay(canvas), XtWindow(canvas));
- }
-
- void expose(Widget w, XtPointer ctx, XtPointer call)
- {
- redraw();
- }
-
- void reset_proj()
- {
- set_toggle(XX_ORTHO, use_ortho);
-
- if (use_ortho) {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-glx_width/2, glx_width/2, -glx_height/2, glx_height/2,
- 0, zsize);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- } else {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(360 * atanf(glx_height / zsize) / M_PI,
- (GLfloat)glx_width / glx_height,
- 0.0, zsize);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
-
- glTranslatef(0.0, 0.0, -zsize/2.0);
- }
-
- static void resize(Widget w, XtPointer ctx, XtPointer call)
- {
- GLwDrawingAreaCallbackStruct *data;
- data = (GLwDrawingAreaCallbackStruct *) call;
-
- glXWaitX();
- glx_width = data->width;
- glx_height = data->height;
- glViewport(0, 0, data->width, data->height);
- reset_proj();
- }
-
- static void initCB(Widget w, XtPointer ctx, XtPointer call)
- {
- glXMakeCurrent(XtDisplay(w), XtWindow(w), ctx);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- set_font(0);
- reset_modes();
- reset_view();
- resize(w, ctx, call);
- }
-
- static void input(Widget w, XtPointer ctx, XtPointer call)
- {
- char buf[31];
- KeySym keysym;
- XEvent *event = ((GLwDrawingAreaCallbackStruct *) call)->event;
- static mstate, omx, omy, mx, my;
-
-
- switch(event->type) {
- case ButtonPress:
- if (event->xbutton.button == Button1) {
- mstate |= 1;
- } else if (event->xbutton.button == Button2) {
- mstate |= 2;
- } else if (event->xbutton.button == Button3) {
- mstate |= 4;
- }
- mx = event->xbutton.x;
- my = event->xbutton.y;
- break;
- case ButtonRelease:
- if (event->xbutton.button == Button1)
- mstate &= ~1;
- if (event->xbutton.button == Button2)
- mstate &= ~2;
- else if (event->xbutton.button == Button3)
- mstate &= ~4;
- break;
- case MotionNotify:
- if (mstate) {
- omx = mx;
- omy = my;
- mx = event->xbutton.x;
- my = event->xbutton.y;
- if (mstate & 1) {
- transX += mx - omx;
- transY += omy - my;
- }
- if (mstate & 2) {
- rotX += my - omy;
- rotY += mx - omx;
- }
- if (mstate & 4) {
- rotZ += mx - omx + omy - my;
- }
- }
- redraw();
- break;
- case KeyRelease:
- XLookupString(&event->xkey, buf, sizeof buf, &keysym, NULL);
- switch(keysym) {
- case '=':
- scale += 1.0;
- redraw();
- break;
- case '-':
- scale -= 1.0;
- redraw();
- break;
- case XK_Escape:
- glcDeleteContext(contextID);
- exit(EXIT_SUCCESS);
- break;
- default:
- break;
- }
- default:
- break;
- }
- }
-
- void fontMenuCB(Widget w, XtPointer client_data, XtPointer call_data)
- {
- set_font((GLint) client_data - fontBase);
- reset_bounds();
- redraw();
- }
-
- void menuCB(Widget w, XtPointer client_data, XtPointer call_data)
- {
- int cmd = (int) client_data;
-
- switch (cmd) {
- case XX_BITMAP:
- case XX_TRIANGLE:
- case XX_LINE:
- set_draw_style(cmd);
- redraw();
- break;
- case XX_RESETVIEW:
- reset_view();
- redraw();
- break;
- case XX_RESETMODE:
- reset_modes();
- redraw();
- break;
- case XX_ORTHO:
- use_ortho = !use_ortho;
- reset_proj();
- redraw();
- break;
- case XX_QUIT:
- glcDeleteContext(contextID);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- }
-
- Widget create_pane(Widget parent)
- {
- Arg args[10];
- Cardinal nn;
-
- nn = 0;
- return XmCreatePulldownMenu(parent, "pane", args, nn);
- }
-
- Widget create_cascade(Widget parent, Widget pane, char *label)
- {
- Arg args[10];
- Cardinal nn;
-
- nn = 0;
- XtSetArg(args[nn], XmNsubMenuId, pane); nn++;
- return XmCreateCascadeButtonGadget(parent, label, args, nn);
- }
-
- Widget create_toggle(Widget parent, char *label, int cmd, void *callback)
- {
- Arg args[10];
- Cardinal nn;
- Widget toggle;
-
- nn = 0;
- XtSetArg(args[nn], XmNvisibleWhenOff, False); nn++;
- toggle = XmCreateToggleButtonGadget(parent, label, args, nn);
- XtAddCallback(toggle, XmNvalueChangedCallback, callback, (XtPointer)cmd);
- menu_buttons[cmd] = toggle;
- return toggle;
- }
-
- Widget create_submenu(Widget parent, MenuPane *data)
- {
- Widget pane, cascade;
- Widget items[20];
- int ii;
-
- pane = create_pane(parent);
- cascade = create_cascade(parent, pane, data->label);
- for (ii = 0; ii < data->icount; ii++)
- items[ii] =
- create_toggle(pane, data->items[ii].label, data->items[ii].cmd,
- menuCB);
- XtManageChildren(items, data->icount);
- return cascade;
- }
-
- Widget create_fontmenu(Widget parent)
- {
- Widget pane, cascade;
- Widget *items;
- int ii;
-
- items = (Widget *) alloca(fontCount * sizeof(Widget));
-
- pane = create_pane(parent);
- cascade = create_cascade(parent, pane, "Family");
- for (ii = 0; ii < fontCount; ii++)
- items[ii] =
- create_toggle(pane, fontNames[ii], fontBase + ii, fontMenuCB);
- XtManageChildren(items, fontCount);
- return cascade;
- }
-
- Widget create_menu(Widget parent)
- {
- Widget menu, pane;
- Arg args[10];
- Widget cb[10];
- Cardinal nn;
- int button_count;
-
- nn = 0;
- XtSetArg(args[nn], XmNrightAttachment, XmATTACH_FORM); nn++;
- XtSetArg(args[nn], XmNleftAttachment, XmATTACH_FORM); nn++;
- XtSetArg(args[nn], XmNtopAttachment, XmATTACH_FORM); nn++;
- menu = XmCreateMenuBar(parent, "menuBar", args, nn);
-
- fontBase = view_menu.icount + style_menu.icount;
- button_count = fontBase + fontCount;
- menu_buttons = (Widget *) malloc( button_count * sizeof(Widget) );
-
- nn = 0;
- cb[nn++] = create_submenu(menu, &view_menu);
- cb[nn++] = create_submenu(menu, &style_menu);
- cb[nn++] = create_fontmenu(menu);
- XtManageChildren(cb, nn);
-
- return menu;
- }
-
- main(int argc, char *argv[])
- {
- Display *dpy;
- XVisualInfo *visinfo;
- GLXContext ctx;
- Widget toplevel, form, frame, menu;
- Arg args[10];
- Cardinal nn;
- XtAppContext appctx;
-
- toplevel = XtOpenApplication(&appctx, "animate", NULL, 0,
- &argc, argv, fallbackResources,
- applicationShellWidgetClass, NULL, 0);
- dpy = XtDisplay(toplevel);
-
- InitFonts();
-
- nn = 0;
- form = XmCreateForm(toplevel, "form", args, nn);
-
- menu = create_menu(form);
- XtManageChild(menu);
-
- nn = 0;
- XtSetArg(args[nn], XmNtopAttachment, XmATTACH_WIDGET); nn++;
- XtSetArg(args[nn], XmNtopWidget, menu); nn++;
- XtSetArg(args[nn], XmNleftAttachment, XmATTACH_FORM); nn++;
- XtSetArg(args[nn], XmNrightAttachment, XmATTACH_FORM); nn++;
- XtSetArg(args[nn], XmNbottomAttachment, XmATTACH_FORM); nn++;
- frame = XmCreateFrame(form, "frame", args, nn);
- XtManageChild(frame);
-
- /* specify visual directly */
- if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), attribs)))
- XtAppError(appctx, "no suitable RGB visual");
-
- nn = 0;
- XtSetArg(args[nn], GLwNvisualInfo, visinfo); nn++;
- canvas = XtCreateWidget("canvas", glwMDrawingAreaWidgetClass,
- frame, args, nn);
-
- ctx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
- XtAddCallback(canvas, GLwNginitCallback, initCB, ctx);
- XtAddCallback(canvas, GLwNexposeCallback, expose, ctx);
- XtAddCallback(canvas, GLwNresizeCallback, resize, ctx);
- XtAddCallback(canvas, GLwNinputCallback, input, ctx);
- XtManageChild(canvas);
-
- XtManageChild(form);
- XtRealizeWidget(toplevel);
-
- XtAppMainLoop(appctx);
- }
-